﻿using SimpleEncryption.Contract;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace SimpleEncryption
{
    public class MainViewModel : INotifyPropertyChanged
    {
        private int numberOfSteps = 50;

        /// <summary>
        /// Gets or sets the number of steps.
        /// </summary>
        public int NumberOfSteps
        {
            get { return numberOfSteps; }
            set { numberOfSteps = value; NotifyChange("NumberOfSteps"); }
        }

        private int numberOfItterations = 100;
        public int NumberOfItterations
        {
            get { return numberOfItterations; }
            set { numberOfItterations = value; NotifyChange("NumberOfItterations"); }
        }


        private string textToEncode = "Niki ist geil";

        /// <summary>
        /// Gets or sets the text to encode.
        /// </summary>
        public string TextToEncode
        {
            get { return textToEncode; }
            set { textToEncode = value; NotifyChange("TextToEncode"); }
        }

        private string textToDecode ;

        /// <summary>
        /// Gets or sets the text to decode.
        /// </summary>
        public string TextToDecode
        {
            get { return textToDecode; }
            set { textToDecode = value; NotifyChange("TextToDecode"); }
        }

        private string password = "asdasd";

        public string Password
        {
            get { return password; }
            set { password = value; NotifyChange("Password"); }
        }
        private List<ICryptoStep> cryptoSteps = new List<ICryptoStep>();

        public ICommand GenerateCryptoStepsCommand { get; private set; }

        public ICommand EncodeCommand { get; private set; }
        public ICommand DecodeCommand { get; private set; }

   


        public MainViewModel()
        {
            GenerateCryptoStepsCommand = new LambdaCommand(() =>
                {
                    cryptoSteps = new List<ICryptoStep>();
                    cryptoSteps.AddRange(CryptoStepGenerator.GenerateLetterReplacement(numberOfSteps));
                    CryptoStepGenerator.random = new Random();
                    cryptoSteps.AddRange(CryptoStepGenerator.GenerateScrambledPositionSteps(numberOfSteps));
                });
            EncodeCommand = new LambdaCommand(() =>
            {
                //here i am just to lazy to think about an algorithm to generate numbers,
                //basically you just need a way to generate unique numbers, could be easily achieved 
                //by limiting the string length, but i am to lazy for this demonstration it should be
                //sufficent
                var baseNumber = password.GetHashCode();

                // i am also to lazy to think of an algorithm to give me always give a 
                //different execution order each time, this should also be sufficent for demonstration
                //i never said you do not need to put work in ;)
                Random executionOrderRandom = new Random(baseNumber);
                string text = TextToEncode;
                for (int i = 0; i < numberOfItterations; i++)
                {
                    var number = executionOrderRandom.Next(0, cryptoSteps.Count - 1);
                    var step = cryptoSteps[number];
                    text = step.Encrypt(text, password);
                }
                TextToDecode = text;
            });
            DecodeCommand = new LambdaCommand(() =>
            {
                //here i am just to lazy to think about an algorithm to generate numbers,
                //basically you just need a way to generate unique numbers, could be easily achieved 
                //by limiting the string length, but i am to lazy for this demonstration it should be
                //sufficent
                var baseNumber = password.GetHashCode();

                // i am also to lazy to think of an algorithm to give me always give a 
                //different execution order each time, this should also be sufficent for demonstration
                //i never said you do not need to put work in ;)
                Random executionOrderRandom = new Random(baseNumber);
                string text = TextToDecode;
                List<ICryptoStep> reveresedList = new List<ICryptoStep>();
                for (int i = 0; i < numberOfItterations; i++)
                {

                    var number = executionOrderRandom.Next(0, cryptoSteps.Count - 1);
                    reveresedList.Add(cryptoSteps[number]);

              
                }
                reveresedList.Reverse();
                foreach (var cryptoStep in reveresedList)
                {
                    text = cryptoStep.Decrypt(text, password);
                }
                TextToEncode = text;
            });
        }

        private void NotifyChange(string name)
        {
            var propChanged = PropertyChanged;
            if (propChanged != null)
            {
                propChanged(this, new PropertyChangedEventArgs(name));
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}
